#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "StdThread.h"
#include "DoubleLinkList.h"
struct StdThread
{
   pthread_t pid;
};

Thread *ThreadInit(void *(*func)(void *), void *arg)
{   
    Thread*t = (Thread*)malloc(sizeof(Thread));
    if(t == NULL)
    {
        perror("malloc");
        return NULL;
    }

    pthread_create(&t->pid,NULL,func,arg);
    return t;
}

void* ThreadJoin(Thread *t)
{   
    void* retval;
    pthread_join(t->pid,NULL);
    return retval;
}

void ThreadDetach(Thread *t)
{
    pthread_detach(t->pid);
}

void ThreadCancel(Thread *t)
{
    pthread_cancel(t->pid);
}

void ThreadExit()
{
    pthread_exit(NULL);
}

bool IsCurrentThread(Thread *t)
{   
    return t->pid == pthread_self();
}

void ClearThread(Thread *t)
{
    free(t);
}



struct StdMutex
{
   pthread_mutex_t mutex;
};

Mutex *MutexInit()
{   
    Mutex * m = (Mutex*)malloc(sizeof(Mutex));
    if(m==NULL)
    {
        printf("mutex malloc error\n");
        return NULL;
    }
    pthread_mutex_init(&m->mutex,NULL);
    return m;
}

void MutexLock(Mutex *m)
{  
     pthread_mutex_lock(&m->mutex);
}

void MutexUnlock(Mutex *m)
{
    pthread_mutex_unlock(&m->mutex);
}

bool MutexTryLock(Mutex *m, int seconds, int count)
{   
    while(count != 0)
    {   
        //上锁成功
        if(pthread_mutex_trylock(&m->mutex) == 0)
        {
            return true;
        }
        else
        {   

            sleep(seconds);
            count--;
        }
    }
    return false;
}

void ClearMutex(Mutex *m)
{
    pthread_mutex_destroy(&m->mutex);
    free(m);
}



struct StdConditionVar
{
    pthread_cond_t cond;
};

Cond *CondInit()
{   
    Cond * c = (Cond*)malloc(sizeof(Cond));
    if(c == NULL)
    {
        printf("Cond malloc error!\n");
        return NULL;
    }

    pthread_cond_init(&c->cond,NULL);
    return c;
}

void CondWait(Cond *c, Mutex *m)
{   
    //阻塞线程等待条件变量信号，放开锁
    pthread_cond_wait(&c->cond,&m->mutex);
}

void CondSignal(Cond *c)
{
    pthread_cond_signal(&c->cond);
}

void CondBroadcast(Cond *c)
{
    pthread_cond_broadcast(&c->cond);
}

void ClearCond(Cond *c)
{
    pthread_cond_destroy(&c->cond);
    free(c);
}

struct StdRWMutex
{
    Mutex *m;
    Cond *readCond;
    Cond *writeCond;
    int writers; //写的线程数量
    int readers; //读的线程数量
    int waitWriters; //等待要写的线程数量
};

RWMutex *RWMutexInit()
{   
    RWMutex *rw = (RWMutex*)malloc(sizeof(RWMutex));
    if(rw == NULL)
    {
        printf("RWMutexInit malloc error!\n");
        return NULL;
    }
    rw->m = MutexInit();
    rw->readCond = CondInit();
    rw->writeCond = CondInit();
    rw->readers = rw->writers = rw->waitWriters = 0;
    return rw;
}

void RwReadLock(RWMutex *rw)
{
    MutexLock(rw->m);
    while(rw->writers > 0||rw->waitWriters > 0)
    {
        CondWait(rw->readCond,rw->m);
    }
    rw->readers++;
    MutexUnlock(rw->m);
}

void RWReadUnlock(RWMutex * rw)
{
    MutexLock(rw->m);
    rw->readers--;
    if(rw->readers == 0)
    {
        CondSignal(rw->writeCond);
    }
    MutexUnlock(rw->m);
}

void RWWritelock(RWMutex *rw)
{ 
    MutexLock(rw->m);
    rw->waitWriters++;
    while(rw->readers > 0 || rw->writers > 0)
    {
        CondWait(rw->writeCond,rw->m);
    }
    rw->waitWriters--;
    rw->writers++;

    MutexUnlock(rw->m);

}

void RWWriteUnlock(RWMutex *rw)
{
    MutexLock(rw->m);
    rw->writers--;
    if(rw->waitWriters > 0)
    {
        CondSignal(rw->writeCond);
    }
    else
    {
        CondBroadcast(rw->readCond);
    }

    MutexUnlock(rw->m);
}

void ClearRwMutex(RWMutex *rw)
{
    ClearMutex(rw->m);
    ClearCond(rw->readCond);
    ClearCond(rw->writeCond);
    free(rw);
}

